package viperSetting

import (
	"encoding/json"
	"errors"
	"gitee.com/leaf-rain-gitee/util/tool"
	"gitee.com/leaf-rain-gitee/util/viperSetting/remote"
	vi "github.com/spf13/viper"
	"time"
)

func init() {
	vi.RemoteConfig = &remote.Config{}
}

var settingMd5 string

type Viper struct {
	*vi.Viper
	SettingClose chan struct{}
}

func NewViper() *Viper {
	return &Viper{
		Viper:        vi.New(),
		SettingClose: make(chan struct{}, 1),
	}
}

func InitViper(etcdAddr, etcdPath, fileName, filePath, configType string) (*Viper, error) {
	var err error
	if (etcdPath == "" || etcdAddr == "") && (fileName == "" || filePath == "") || configType == "" {
		return nil, errors.New("配置参数为空")
	}
	v := NewViper()
	v.SetConfigType(configType)

	if etcdPath != "" && etcdAddr != "" { // 优先从etcd中读取配置
		err = v.AddRemoteProvider("etcd", etcdAddr, etcdPath)
		if err != nil {
			return nil, err
		}
		err = v.ReadRemoteConfig()
		if err != nil {
			return nil, err
		}
		settingMd5 = settingToMd5(v)
		// open a goroutine to watch remote changes forever
		go func() {
			defer close(v.SettingClose)
			for {
				time.Sleep(time.Second * 5) // delay after each request

				// currently, only tested with etcd support
				err := v.WatchRemoteConfig()
				if err != nil {
					continue
				}
				newSettingMd5 := settingToMd5(v)
				if newSettingMd5 != settingMd5 {
					settingMd5 = newSettingMd5
					v.SettingClose <- struct{}{}
				}
			}
		}()
	} else { // 从文件中读取
		v.AddConfigPath(filePath)
		v.SetConfigName(fileName)
		if err = v.ReadInConfig(); err != nil {
			return nil, err
		}
	}
	return v, nil
}

func settingToMd5(v *Viper) string {
	setting := v.AllSettings()
	js, _ := json.Marshal(setting)
	return tool.GetMD5Encode(js)
}
